package com.platform.common.cache.redis.serializer;

import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;

public class MsgPackRedisSerializer<T> implements RedisSerializer<T> {

	private final ObjectMapper mapper = MsgPackSerializerHelper.OBJECT_MAPPER;
	private final JavaType javaType;

	/**
	 * Creates a new {@link MsgPackRedisSerializer} for the given target {@link Class}.
	 * 
	 * @param type
	 */
	public MsgPackRedisSerializer(Class<T> type) {
		this.javaType = getJavaType(type);
	}

	/**
	 * Creates a new {@link MsgPackRedisSerializer} for the given target {@link JavaType}.
	 * 
	 * @param javaType
	 */
	public MsgPackRedisSerializer(JavaType javaType) {
		this.javaType = javaType;
	}

	@Override
	public byte[] serialize(T t) throws SerializationException {
		if (t == null) {
			return MsgPackSerializerHelper.EMPTY_ARRAY;
		}
		try {
			return this.mapper.writeValueAsBytes(t);
		} catch (Exception ex) {
			throw new SerializationException("Could not write JSON use msgpack: " + ex.getMessage(), ex);
		}
	}

	@Override
	public T deserialize(byte[] bytes) throws SerializationException {
		if (bytes == null || bytes.length == 0) {
			return null;
		}
		try {
			return (T) this.mapper.readValue(bytes, 0, bytes.length, javaType);
		} catch (Exception ex) {
			throw new SerializationException("Could not read JSON use msgpack: " + ex.getMessage(), ex);
		}
	}

	protected JavaType getJavaType(Class<?> clazz) {
		return TypeFactory.defaultInstance().constructType(clazz);
	}
}
